I have a component with 2 LinearGradient views, both of them with absolute position and one with TextInput. For this setting, TextInput never gains focus in Android.
Code:
class SearchScreen extends Component {
render() {
return (
<View style={{ flex: 1 }}>
<LinearGradient
colors={['blue', 'red']}
style={{
height: 80,
width: '100%',
position: 'absolute',
zIndex: 10,
elevation: 10,
top: 0,
left: 0,
}}
start={{ x: 0, y: 0 }}
end={{ x: 1, y: 0 }}
>
<TextInput
style={{
backgroundColor: 'white',
height: 50,
paddingLeft: 15,
marginTop: 10,
marginBottom: 10,
marginRight: 20,
marginLeft: 20,
borderWidth: 0,
}}
placeholder={'search placeholder'}
onFocus={() => { console.log('onFocus: '); }}
onChangeText={(text) => { console.log('enter text: ', text); }}
onEndEditing={() => { console.log('endEditing: '); }}
/>
</LinearGradient>
<LinearGradient
colors={['red', 'blue']}
style={{
height: 150,
width: '100%',
position: 'absolute',
zIndex: 5,
elevation: 5,
}}
>
</LinearGradient>
</View >
);
}
}
export default SearchScreen;
React Native: 0.55.2
react-native-linear-gradient: 2.4.0
I found the problem is with the 2 absolute positioned LinearGradient View with Text Input. If I remove the one of the LinearGradient, the TextInput works fine as it should.
I've tried providing zIndex to the TextInput too, it doesn't work.
Thanks.
Seems like a bug in the zIndex for android, as it works fine for IOS.
You can use it the following way as a workaround by nesting of linear gradients so that there is no conflict for the overlay element that renders.
<LinearGradient
colors={['red', 'blue']}
style={{
height: 150,
width: '100%',
position: 'absolute',
zIndex: 5,
elevation: 5,
}}
>
<LinearGradient
colors={['blue', 'red']}
style={{
height: 80,
width: '100%',
position: 'absolute',
zIndex: 10,
elevation: 10,
top: 0,
left: 0,
}}
start={{ x: 0, y: 0 }}
end={{ x: 1, y: 0 }}
>
<TextInput
style={{
backgroundColor: 'white',
height: 50,
paddingLeft: 15,
marginTop: 10,
marginBottom: 10,
marginRight: 20,
marginLeft: 20,
borderWidth: 0,
}}
placeholder={'search placeholder'}
onFocus={() => { console.log('onFocus: '); }}
onChangeText={(text) => { console.log('enter text: ', text); }}
onEndEditing={() => { console.log('endEditing: '); }}
/>
</LinearGradient>
</LinearGradient>
Related
I created a hook to capture the react-native-pager-view carousel scroll position:
import { useEvent, useHandler } from 'react-native-reanimated';
import { AnimatedPagerScrollHookParams } from './animated-pager-scroll.type';
const useAnimatedPagerScroll = (
handlers: AnimatedPagerScrollHookParams['handlers'],
dependencies?: AnimatedPagerScrollHookParams['dependencies'],
) => {
const { context, doDependenciesDiffer } = useHandler(handlers, dependencies);
return useEvent(
event => {
'worklet';
const { onPageScroll } = handlers;
if (
onPageScroll &&
(
event as {
eventName: string;
}
).eventName.endsWith('onPageScroll')
) {
onPageScroll(event, context);
}
},
['onPageScroll'],
doDependenciesDiffer,
);
};
export default useAnimatedPagerScroll;
And then, I used it in my PagerView component like so:
<AnimatedPagerView
onPageScroll={handler}
style={{ flex: 1 }}
initialPage={0}
>
{slides.map((slide, index) => (
<View
key={index}
style={{
justifyContent: 'center',
alignItems: 'center',
}}
>
<ImageBackground
testID="TestID__image-Onboarding"
source={slide.imageUrl}
style={{
width: '100%',
height: '100%',
justifyContent: 'flex-end',
}}
>
<LinearGradient
colors={['rgba(255,255,255,1)', 'rgba(255,255,255,0)']}
style={{
position: 'absolute',
left: 0,
right: 0,
top: 0,
height: '50%',
}}
/>
<Typography
testID="TestID__subtitle-Onboarding"
variant="h1"
color="alternateBasic"
style={{
marginBottom: 146,
marginLeft: 43,
width: index === slides.length - 1 ? '45%' : '35%',
}}
>
{slide.subtitle}
</Typography>
</ImageBackground>
</View>
))}
</AnimatedPagerView>
I am using a library called react-native-animated-pagination-dots. It animates based on the scroll position. It accepts a prop called scrollX which has to be of type Animated.Value. I am using react-native-reanimated
<ExpandingDot
data={slides}
expandingDotWidth={30}
scrollX={translationY.value}
inActiveDotOpacity={0.6}
dotStyle={{
width: 10,
height: 10,
backgroundColor: '#347af0',
borderRadius: 5,
marginHorizontal: 5,
}}
containerStyle={{
top: 30,
}}
/>
It throws an error if I pass a shared value which I can understand as it expects Animated.Value. What transformation can I perform to continue using react-native-reanimated and satisfy the condition of the library by passing the right prop?
Library List:
https://github.com/weahforsage/react-native-animated-pagination-dots
https://github.com/callstack/react-native-pager-view
https://docs.swmansion.com/react-native-reanimated/
Do as following and let me know it works or not:
scrollX={new Animated.value(translationY.value)}
I believe you need to pass the translationY directly (without .value):
<ExpandingDot
data={slides}
expandingDotWidth={30}
scrollX={translationY}
inActiveDotOpacity={0.6}
dotStyle={{
width: 10,
height: 10,
backgroundColor: '#347af0',
borderRadius: 5,
marginHorizontal: 5,
}}
containerStyle={{
top: 30,
}}
/>
Hope it helps.
If you look at other examples, you can see them reacting immediately.
But my code reacts slowly.
If you watch the video, you can see what I mean.(https://youtu.be/jo_iDDh2WBw)
Please tell me a solution to this.
Below is my code.
<SafeAreaView style={{...structure.safeViewContainer, backgroundColor: "#ffffff"}}>
<View style={{...structure.container}}>
<BlurView intensity={100} style={{...structure.headerBox}}>
<Header arrow={false} navigation={navigation} />
</BlurView>
<ScrollView style={{...structure.contentContainer, overflow: 'visible', backgroundColor: colors.lightGray}}>
<View style={structure.contentBox}>
<View style={{ right: 0, left: 0, backgroundColor: "#000000", height: 300, borderRadius: 20 }}></View>
<View style={{ right: 0, left: 0, backgroundColor: "#ffffff", height: 300, marginTop: 30, borderRadius: 20 }}></View>
<View style={{ right: 0, left: 0, backgroundColor: "#ffffff", height: 300, marginTop: 30, borderRadius: 20 }}></View>
<View style={{ right: 0, left: 0, backgroundColor: "#ffffff", height: 300, marginTop: 30, marginBottom: 55, borderRadius: 20 }}></View>
</View>
</ScrollView>
<View style={{ backgroundColor: colors.lightGray, right: 0, left: 0, height: 20, bottom: -20, position: "absolute" }}></View>
</View>
<TabBar navigation={navigation} />
</SafeAreaView>
I want to freeze the customer profile component when user scrolling the page, so I set the scrollY value to translateY property to avoid the component from moving up. However, on android device, when the user scroll slightly faster, the component will become a little bit shaky even I have already added useNativeDriver: true.
Really APPRECIATE if anyone could help, was struggling for quite a number of days.
Below is the code for the entire screen:
const scrollY = React.useRef(new Animated.Value(0)).current;
<Animated.ScrollView
scrollEventThrottle={16}
automaticallyAdjustContentInsets={false}
contentContainerStyle={{ flexGrow: 1 }}
contentInsetAdjustmentBehavior="automatic"
bounces={false}
showsVerticalScrollIndicator={false}
onScroll={Animated.event(
[{ nativeEvent: { contentOffset: { y: scrollY } } }],
{ useNativeDriver: true }
)}
>
<Animated.View
style={{
width: deviceWidth,
height: 250,
backgroundColor: 'lightgrey',
paddingHorizontal: 30,
justifyContent: 'center',
alignItems: 'center',
transform: [
{
translateY: scrollY
}
]
}}
>
<View
style={{
borderRadius: 100 / 2,
width: 100,
height: 100,
backgroundColor: 'white',
marginBottom: 20
}}
></View>
<Text style={{ marginBottom: 5, fontSize: 22 }}>Chris Groves</Text>
<Text style={{ fontSize: 30, fontWeight: 'bold' }}>$ 190.83</Text>
</Animated.View>
<View
style={{
backgroundColor: 'white',
justifyContent: 'center',
alignItems: 'center'
}}
>
<View
style={{
height: 200,
width: 350,
backgroundColor: 'red',
marginVertical: 30
}}
/>
<View
style={{
height: 200,
width: 350,
backgroundColor: 'red',
marginBottom: 30
}}
/>
<View
style={{
height: 200,
width: 350,
backgroundColor: 'red',
marginBottom: 30
}}
/>
<View style={{ height: 200, width: 350, backgroundColor: 'red' }} />
</View>
</Animated.ScrollView>
Demo video for better understanding:
Demo Video
I am trying to make my own tab navigation like Instagram has instagram example. I noticed that the items within the footer view I made does not stay within the bounds and moves to the top left of the screen. Images shown - What I am trying to achieve What happens frequently
Here is the most important part of my code. I have done inline styles temporarily to try and figure out the issue. Here is the part where the issue lays <View style = {{ width: Dimensions.get('window').width, backgroundColor: '#fff', height: 80}} <TouchableOpacity onPress = {() => this.props.navigation.navigate('Profile')} style = {{justifyContent: 'flex-end'}}>
<Text style = {{justifyContent: 'flex-end'}}> Profile </Text>
</TouchableOpacity> </View>-
render() {
return (
<MapView style = {[style.container, style.map]}
region = {this.state.initialPosition}>
<MapView.Marker coordinate = {this.state.markerPosition}>
<View style = {style.radius}>
<View style = {style.marker}/>
</View>
</MapView.Marker>
<View style = {{ width: Dimensions.get('window').width, backgroundColor: '#fff', height: 80}} >
<TouchableOpacity onPress = {() => this.props.navigation.navigate('Profile')} style = {{justifyContent: 'flex-end'}}>
<Text style = {{justifyContent: 'flex-end'}}> Profile </Text>
</TouchableOpacity>
</View>
</MapView>
);
}
}
const style = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'flex-end',
//alignItems: 'center',
},
text: {
color: '#fff'
},
map: {
left: 0,
right: 0,
top: 0,
bottom: 0,
position: 'absolute'
},
radius:{
height: 50,
width: 50,
borderRadius: 50 / 2,
overflow: 'hidden',
backgroundColor: 'rgba(1,213,106,0.3)',
borderWidth: 1,
borderColor: 'rgba(1,213,106,0.3)',
alignItems:'center',
justifyContent: 'center'
},
marker: {
height: 20,
width: 20,
borderWidth: 3,
borderColor: '#fff',
borderRadius: 20 / 2,
borderWidth: 3,
overflow: 'hidden',
backgroundColor: '#01D56A'
},
menuSection: {
backgroundColor: 'rgba(255, 255, 255, 0.7)',
width: Dimensions.get('window').width,
height: Dimensions.get('window').height/3,
justifyContent: 'flex-end',
alignItems: 'center'
},
icon:{
width: 50,
height: 50,
backgroundColor: 'black'
}
})
In my code i have 2 textInputs, one has one line and the other has multiple lines, the input is arabic so i have to enable textAlign: 'right',
my problem is when i set multilines to true, the placeholder text remains on the left side of the text input,
any idea how to solve this?
my code is the following:
View:
<View style={{ position: 'relative' }}>
<TextInput
style={forms.textInput}
value={this.state.telephone}
placeholder={'رقم هاتفك'}
placeholderTextColor={'rgba(0,0,0,0.6)'}
onChangeText={(val) => this.setState({telephone: val}) } />
<Icon name="android-phone-portrait" size={27} color="rgba(0,0,0,0.6)" style={{ position: 'absolute', top: 10, right: 24 }}/>
</View>
<View style={{ position: 'relative' }}>
<TextInput
style={[forms.textInput,{height: 120}]}
multiline={true}
value={this.state.desc}
numberOfLines={4}
placeholder={'اقتراحك'}
placeholderTextColor={'rgba(0,0,0,0.6)'}
onChangeText={(val) => this.setState({desc: val}) }/>
<Icon name="ios-help-outline" size={27} color="rgba(0,0,0,0.6)" style={{ position: 'absolute', top: 10, right: 24 }}/>
</View>
Style:
textInput: {
height: 40,
borderColor: 'rgba(0, 0, 0, 0.4)',
borderWidth: 2,
margin: 15,
marginTop: 5,
backgroundColor: '#fff',
color: 'rgba(0, 0, 0, 0.9)',
paddingRight: 40,
textAlign :'right'
},
______________________*******________________________
______________________*******________________________
I have actually made a pull request for this which has been accepted and will be in the 0.29.0 release of react-native.
My fix was to add this line
_placeholderView.textAlignment = _textView.textAlignment;
to react-native/Libraries/Text/RCTTextView.m
Inside the updatePlaceholder function (right before [self insertSubview:_placeholderView belowSubview:_textView];)
GitHub Commit