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>
Related
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;
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
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>
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>
```
I want to put the string 'example' in the middle of the header.
Code:
<View style={viewStyle}>
<ImageButton
imageUrl={require('./assets/icons/Back-25.png')}
onPress={props.onPressPhone}
/>
<Text>{props.headerText}</Text>
</View>
viewStyle:
backgroundColor: 'white',
alignItems: 'center',
height: 60,
paddingTop: 15,
shadowColor: '#000000',
shadowOffset: { width: 0, height: 1 },
shadowOpacity: 0.2,
elevation: 2,
position: 'relative',
flexDirection: 'row',
justifyContent: 'space-between',
Image Button style:
alignSelf: 'center',
One way to do this is to use a same-size empty .png image on the other side, and space-between in your header styling:
<View style={ styles.header }>
<Button style={{left: 10}} onPress={ () => this.handlePress() }>
<Image source={ require('../images/arrow_back.png') } style={{ width: 50, height: 50 }} />
</Button>
<Text style={styles.header_text} >{this.props.title}</Text>
<Button style={{right: 10}}>
<Image source={ require('../images/no_image.png') } style={{ width: 50, height: 50 }} />
</Button>
</View>
and
header: {
flex: 1,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
width: width,
backgroundColor: '#09146d',
},
...a bit kludgy, but it has worked for me. Alternatively, you could divide up the header with flex-based views, using flexDirection: 'row' :
<View style={ styles.header }>
<View style={{flex: 1}}>
//Button in here
</View>
<View style={{alignItems: 'center', flex: 6}}>
//Text in here
</View>
<View style={{flex: 1}}>
//Nothing in here
</View>
</View>
Good luck!
Expand on kwishnu's flex idea:
flex: 1; will always allocate only 1/3rd of the width to the title. So use flex: 1 1 auto; instead to allow the title to expand into all available space.
add min-width: fit-content; to the back button (so that the title will never cover the back button).
Add bonus styling in the case where the title is really, really long
span {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
<div class="header" style="display: flex;">
<span style="flex: 1; background: aqua; min-width: fit-content;">Back Button</span>
<span style="flex: 1 1 auto; text-align: center; background: beige;">Edit title to see behaviour whien title is very long</span>
<span style="flex: 1; background:red;"></span>
</div>