Align view and Text for responsive screen in React Native - react-native

I want to align all view and text parts like the above image. if the number may be big or small but the upper title should be in the middle of the value.
same alignment for the right side views also.
and the view and alignment should be responsive for every ios and android.
I have tried:
<ZekifutSchumView>
<ZekifutSchumText>סה”כ</ZekifutSchumText>
</ZekifutSchumView>
<HefreshimForLoTashlumView>
<HefreshimForLoTashlumText>
{props.hefreshimTotalForLoTashlum}
</HefreshimForLoTashlumText>
</HefreshimForLoTashlumView>
const ZekifutSchumText = styled(Text)``;
const ZekifutSchumView = styled(View)`
right: 2px;
`;
const HefreshimForLoTashlumView = styled(View)`
top: 15px;
${Platform.select({
ios: `
right: 30px;
`,
android: `
right: 26px;
`,
})};
border-right-width: 1px;
border-color: #ddd;
height: 18px;
`;
const HefreshimForLoTashlumText = styled(Text)`
${Platform.select({
ios: `
right: 20px;
`,
android: `
right: 21px;
`,
})};
`;
The same code is for the right side view also.
How can I align these view??

<View style={styles.app}>
<View style={{flexDirection: 'row', justifyContent: 'space-evenly'}}>
<View style={{alignItems: 'center'}}>
<Text>$</Text>
<Text>123,345,77</Text>
</View>
<View style={{
height: '50%',
width: 1,
backgroundColor: 'grey',
position: 'absolute',
bottom: 0}}/>
<View style={{alignItems: 'center'}}>
<Text>$</Text>
<Text>123,345,77</Text>
</View>
</View>
</View>
Note: pls do not use inline styles, just added them here for easy viewing

Related

Horizontal ScrollView Not Scrolling in React Native

I'm trying to render a horizontal scroll view of clickable photos.
The vertical scroll works fine, but once I set horizontal={true}, I'm limited to how far I can scroll horizontally. It prevents me from scrolling more than what is shown in this image.
<Container>
<ScrollView
horizontal={true}
contentContainerStyle={{
flex: 1,
paddingTop: "5%"
}}
>
{posts.map(post => {
return (
<TouchableOpacity
key={post.id}
style={{
width: width,
flex: 1,
height: height / 3,
borderRadius: "8px",
overflow: "hidden",
marginRight: "2%"
}}
>
<Thumbnail
source={{
uri: uri`
}}
/>
<PostTitle>{post.name}</PostTitle>
</TouchableOpacity>
);
})}
</ScrollView>
</Container>
const Container = styled.View`
flex: 1;
padding-top: 18%;
background: #fff;
`;
const Title = styled.Text`
color: #333;
text-transform: uppercase;
font-weight: 600;
padding-left: 8%;
padding-bottom: 5%;
`;
const Thumbnail = styled.Image`
flex: 1;
justify-content: center;
align-items: center;
resize-mode: cover;
`;
const PostTitle = styled.Text`
color: #fdfdfd;
font-size: 16px;
font-weight: bold;
position: absolute;
top: 10%;
left: 8%;
`;
Fixed. Removed "marginRight" and it worked. Horizontal ScrollView doesn't like styling its children's margins.
The problem certainly is from the margin. However, I've found that specifically, setting the margin in percentage values or adding flex: 1 to contentContainerStyle is what causes this problem.

Adding a solid stroke to Text

I am trying to add a thick solid stroke to some Text in React Native. I've added a snippet with the desired CSS.
I've tried directly applying the CSS via styled-components but I get an error stating that my value is unable to be parsed.
const Title = styled.Text`
text-shadow: 2px 2px 0px #000, -2px -2px 0px #000, 2px -2px 0px #000, -2px 2px 0px #000;
`;
I have tried using textShadow but this does not apply a solid stroke. This prop relies on a width and height prop for an offset.
Here's a snack for example - https://snack.expo.io/#hannigan/ba7574
h1 {
text-shadow: 2px 2px 0px #000, -2px -2px 0px #000, 2px -2px 0px #000, -2px 2px 0px #000;
color: white;
font-family: 'Arial';
}
<h1>Hello World</h1>
So this works for me, are you sure that it won't work for you in dynamic height?
Edit: I might have now found what you were talking about. I am checking if I can update the snack to work for dynamic views.
Edit2: Alright, made it work. You just need to make the first text non-absolute.
https://snack.expo.io/Bk8ifP!4I
Edit3: As mentioned by Vencovsky it might break if you need to use flex around it. You can hack it with a onLayout like in this Snack: https://snack.expo.io/HJ!PRUKNL
basically you save the height of the text and then use it for height and margin on other views. It hacky, but I have used it in other settings and works fine.
export default class App extends React.Component {
render() {
const myText = 'Hello World. This is my very long text, that can be a few lines height'
return (
<View style={styles.container}>
<View>
<Text style={[styles.paragraph]}>{myText}</Text>
<Text style={[styles.paragraph, styles.abs, {textShadowOffset: {width: -2, height: -2}}]}>{myText}</Text>
<Text style={[styles.paragraph, styles.abs, {textShadowOffset: {width: -2, height: 2}}]}>{myText}</Text>
<Text style={[styles.paragraph, styles.abs, {textShadowOffset: {width: 2, height: -2}}]}>{myText}</Text>
</View>
<Text> 'Here another text' </Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8
},
paragraph: { fontSize: 50, color: '#FFF', textShadowColor: 'black', textShadowRadius: 1, textShadowOffset: {
width: 2,
height: 2
}},
abs: {
position: 'absolute',
top: 0, left: 0, right: 0, bottom: 0
}
});
I couldn't find a way to do this with react native's css but I found a way to do a stoke in the text with react-native-svg
<Svg height="60" width="200">
<Text
fill="none"
stroke="purple"
fontSize="20"
fontWeight="bold"
x="100"
y="20"
textAnchor="middle"
>
STROKED TEXT
</Text>
</Svg>
Edit
I know this answer isn't the perfect one, but so far is the only answer I found to do this, but unfortunately it isn't good for dynamic text.

Icon to de right side of the view React-native

im trying to keep my icon in the right side of View component. But im failed.
<StyledView>
<StyledListItem {...props}>
{value}
<Icon name="add" size={24} style={{ right: 0 }} />
</StyledListItem>
<StyledLine></StyledLine>
</StyledView>
styles components:
import styled from 'styled-components/native';
import colors from "../../../styles/colors";
import { styledfont } from "../../../styles/fonts";
export const StyledList = styled.TextInput`
height: 40px;
border: 1px solid gray;
width: 100%;
padding: 0 10px;
`;
export const StyledListItem = styled.Text`
${styledfont.h4}
color: ${colors.blue.primary};
width: 72%;
margin-bottom: 15px;
margin-top: 13px;
margin-left:28px;
flex-direction: row;
`;
export const StyledView = styled.View`
width: 100%;
height: 68px;
`;
export const StyledLine = styled.View`
width: 100%;
height: 1px;
background-color: ${colors.blue.primaryopc20};
`;
export const StyledContainer = styled.View`
width: 100%;
top: 0;
flex: 1;
`;
I try a lot of things, someone can help me? I think that I should use something like flex row, but I do not know how to apply that.
You can add positioning to your components. In this case, I'd try:
<StyledView>
<StyledListItem style={{position: 'relative'}} {...props}>
{value}
<Icon name="add" size={24} style={{ position: 'absolute', right: 0 }} />
</StyledListItem>
<StyledLine></StyledLine>
</StyledView>
You can even leave out the relative positioning on the parent since in react native everything is positioned relative by default
you can wrap icon in view and use marginLeft:'auto' property as:-
```
<StyledView>
<StyledListItem {...props}>
{value}
<View style={{marginLeft:'auto'}}>
<Icon name="add" size={24} style={{ right: 0 }} />
</View>
</StyledListItem>
<StyledLine></StyledLine>
</StyledView>
```

Background border view with up-arrow triangle | React Native

I need to create the background view like this -
The background view with border must have up-arrow triangle.
This is my current code snippet -
<View style={{ width: '100%', paddingLeft: basePadding, paddingRight: basePadding }}>
<View style={{width: '100%', flexDirection: 'row', justifyContent: 'space-between', alignItems: 'flex-start', flex: 1}}>
<View style={{
marginTop: 10,
width: horizScale(30),
borderBottomWidth: StyleSheet.hairlineWidth,
borderColor: Colors.fire,
height: 1
}}/>
<View style={{
flex: 1,
marginTop: 10,
marginLeft: horizScale(20),
borderBottomWidth: StyleSheet.hairlineWidth,
borderColor: Colors.fire,
height: 1
}}/>
</View>
<View style={{width: '100%', borderLeftWidth: StyleSheet.hairlineWidth, borderRightWidth: StyleSheet.hairlineWidth, borderBottomWidth: StyleSheet.hairlineWidth, borderColor: Colors.fire, backgroundColor: '#FEF6F7', padding: horizScale(20)}}>
<Text style={{color: '#403F41'}}>
{' Test Test Test Test test'}
</Text>
<View style={{ flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'flex-start',
marginTop: horizScale(10),
width: '100%'}}>
<TouchableOpacity onPress={() => {
}}
style={{
backgroundColor: Colors.fire,
flex: 1,
alignItems: 'center',
justifyContent: 'center',
height: horizScale(40),
borderRadius: 3,
marginRight: horizScale(10)
}}>
<HeavyText style={{ fontSize: horizScale(14), color: '#FFF' }}>{'CANCEL'}</HeavyText>
</TouchableOpacity>
<TouchableOpacity onPress={() => {
}}
style={{
backgroundColor: primaryColor,
flex: 1,
alignItems: 'center',
marginLeft: horizScale(10),
justifyContent: 'center',
height: horizScale(40),
borderRadius: 3
}}>
<HeavyText style={{ fontSize: horizScale(14), color: '#FFF' }}>{'RE-BOOK'}</HeavyText>
</TouchableOpacity>
</View>
</View>
</View>
Add 2 triangle one for background color and one for border color
Complete code
import React, { Component } from "react";
import { View, StyleSheet } from "react-native";
export default class Dashboard extends Component {
render() {
return (
<View style={styles.box}>
<View style={styles.triangle} />
<View style={styles.triangle2} />
</View>
);
}
}
const styles = StyleSheet.create({
box: {
width: 300,
height: 100,
backgroundColor: "#fef6f7",
position: "relative",
margin: 50,
borderColor: "red",
borderWidth: 1
},
triangle: {
width: 10,
height: 10,
position: "absolute",
top: -10,
left: 20,
borderLeftWidth: 10,
borderLeftColor: "transparent",
borderRightWidth: 10,
borderRightColor: "transparent",
borderBottomWidth: 10,
borderBottomColor: "red"
},
triangle2: {
width: 10,
height: 10,
position: "absolute",
top: -10,
left: 21,
borderLeftWidth: 9,
borderLeftColor: "transparent",
borderRightWidth: 9,
borderRightColor: "transparent",
borderBottomWidth: 9,
borderBottomColor: "#fef6f7"
}
});
JSX:
<View style={styles.box}>
<View style={styles.triangle}>
</View>
Styling:
box:{
width:100,
height:100,
backgroundColor:"lightblue",
position:"relative"
},
triangle:{
width:10,
height:10,
position:"absolute",
top:-10,
left:20,
borderLeftWidth:10,
borderLeftColor:"transparent",
borderRightWidth:10,
borderRightColor:"transparent",
borderBottomWidth:10,
borderBottomColor:"red"
}
Here is the result:
You can change size of the triangle by playing with width and height. Also, if you want to change location, try playing with top and left properties of triangle.
Here are examples for top, right, bottom and left arrows in css. To convert to react native css, just change the properties to camel case. If you are using styled-components, you can use it as is.
Top Arrow:
.topArrow {
border-top-width: 0px;
border-top-color: transparent;
border-right-width: 80px;
border-right-color: transparent;
border-bottom-width: 160px;
border-bottom-color: green;
border-left-width: 80px;
border-left-color: transparent;
border-style: solid;
height: 0px;
width: 0px;
}
<div class="topArrow"></div>
Right Arrow:
.rightArrow {
border-top-width: 80px;
border-top-color: transparent;
border-right-width: 0px;
border-right-color: transparent;
border-bottom-width: 80px;
border-bottom-color: transparent;
border-left-width: 160px;
border-left-color: green;
border-style: solid;
height: 0px;
width: 0px;
}
<div class="rightArrow"></div>
Bottom Arrow:
.bottomArrow {
border-top-width: 160px;
border-top-color: green;
border-right-width: 80px;
border-right-color: transparent;
border-bottom-width: 0;
border-bottom-color: transparent;
border-left-width: 80px;
border-left-color: transparent;
border-style: solid;
height: 0px;
width: 0px;
}
<div class="bottomArrow"></div>
Left Arrow:
.leftArrow {
border-top-width: 80px;
border-top-color: transparent;
border-right-width: 160px;
border-right-color: green;
border-bottom-width: 80px;
border-bottom-color: transparent;
border-left-width: 0px;
border-left-color: transparent;
border-style: solid;
height: 0px;
width: 0px;
}
<div class="leftArrow"></div>

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>