I have tried using a FlatList and a map function to generate a list of entries, but I am getting random lines between the entries (see the blue part of my screenshot)
What is causing these and how can I remove them?
Here is my FlatList:
<FlatList
data={TriageTransfertData[0].content[0].content}
renderItem={({ item }) => (
<View style={styles.subentryContainer}>
<View style={styles.ttEntryFirst} />
<View style={styles.ttEntryContentSub}>
<Text style={styles.ttTextSub}>{item.text}</Text>
</View>
</View>
)}
keyExtractor={item => item.text} />
And here is the styling:
subentryContainer: {
flexDirection: 'row',
width: '100%',
},
ttEntryFirst: {
width: '2%',
backgroundColor: Colors.Blue
},
ttEntryContentSub: {
width: '98%',
justifyContent: 'center',
paddingLeft: responsiveWidth(2),
paddingTop: 10,
paddingBottom: 10,
borderTopWidth: 1,
borderColor: Colors.GreyLight
},
And finally, here is a screenshot (notice the unwanted line in the blue area):
I think you're talking about ItemSeparatorComponent. It's rendered by default in a FlatList, but you can override it passing a custom component or a blank code function.
Here is the brief doc.
Hope this helps!
Related
I want to do something like as shown in the image below but I don't have any idea how to achieve that (I googled it, but I found only result for native code Swift, Obj C, ...).
Do I have to play with some layers or something like that?
Thanks for your answers!
Viktor
Hey thank you so much for your answers,
I had to handle the text overflow with ellipsis and it was really complicated with what you proposed, so I used the maskView to do that.
I did like that:
// container
<View style={{flex:1, borderRadius: 200, height: 25, overflow:hidden}}>
// Progress bar support
<View style={{flex:1, backgroundColor: 'gray'}} />
// Progress bar, I play with "width" to indicate percentage
<View style={[StyleSheet.absoluteFill, {width: "50%", backgroundColor: 'green'}]} />
<MaskedView
style={[StyleSheet.absoluteFill, {justifyContent: 'center'}]}
maskElement={
// I define text which will be masked
<View style={[StyleSheet.absoluteFill, {justifyContent: 'center'}]}>
<Text
style={{marginHorizontal: 15, fontSize: 13}}
numberOfLines={1}>
Text color change
</Text>
</View>
}>
// I define a default mask that I apply to the text so that it is 'black' when it is not ON the progress bar.
<View style={[StyleSheet.absoluteFill,{backgroundColor: 'black'}]} />
// I define the mask that takes the size of the progress bar and that I apply over the default mask (to overwrite it) so that the text under the mask becomes white.
<View style={[StyleSheet.absoluteFill,{width:"50%", backgroundColor: '#fff'}]} />
</MaskedView>
</View>
So I have my default bar indicating the "maximum progress" and I define my progress bar (which grows or shrinks according to the percentage).
Then I define a MaskedView with my text as MaskedElement.
By default, I apply a black mask on the text so that it is always black no matter what happens.
And then, I overwrite this mask with the white mask which has exactly the same size as my progress bar.
So everything under the mask of the progress bar becomes white to go on my "dark" progress bar and the rest is black!
This way, I can easily manage the text overflow with an ellpsizeMode="tail".
And this is the result:
Same styles from the previous answer but changed the implementation by adding another View that contains same text with different background color and text color inside the gray one with a position of 'absolute'!
import * as React from 'react';
import { Text, View, StyleSheet } from 'react-native';
export default class Example extends React.Component {
state = {
text: 'Text color changes',
};
render() {
console.log(this.state.textArray);
return (
<View style={styles.container}>
<View
style={{
flex: 1,
backgroundColor: '#d0d3d6',
borderTopRightRadius: 20,
borderBottomRightRadius: 20,
borderTopLeftRadius: 20,
borderBottomLeftRadius: 20,
overflow: 'hidden',
}}>
<Text style={styles.leftLabelStyle}>{this.state.text}</Text>
<View
style={{
width: '30%',
height: '100%',
position: 'absolute',
backgroundColor: '#5483b3',
}}>
<Text numberOfLines={1} ellipsizeMode='clip'
{styles.RightLabelStyle}>
{this.state.text}
</Text>
</View>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
marginHorizontal: 20,
},
leftLabelStyle: {
fontSize: 16,
paddingVertical: 5,
color: '#000',
},
RightLabelStyle: {
fontSize: 16,
paddingVertical: 5,
color: '#fff',
},
});
example at snack:https://snack.expo.io/#hassan190011/loading
Edit : add ellipsizeMode='clip' after numberOfLines to remove dots
This implementation is a little bit different, Mainly I have 2 different views with separate styles & Finally, wrap those 2 views using the main view.
import * as React from "react";
import { Text, View, StyleSheet } from "react-native";
export default class Example extends React.Component {
render() {
return (
<View style={styles.container}>
<View style={styles.leftViewStyle}>
<Text style={styles.leftLabelStyle}>Text color ch</Text>
</View>
<View style={styles.rightViewStyle}>
<Text style={styles.rigthLabelStyle}>ange</Text>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: "row",
alignItems: "center",
justifyContent: "center",
marginHorizontal: 20
},
leftViewStyle: {
flex: 1,
backgroundColor: "#5483b3",
alignItems: "flex-end",
borderTopLeftRadius: 20,
borderBottomLeftRadius: 20
},
rightViewStyle: {
flex: 1,
backgroundColor: "#d0d3d6",
borderTopRightRadius: 20,
borderBottomRightRadius: 20
},
leftLabelStyle: {
fontSize: 16,
paddingVertical: 5,
color: "#fff"
},
rigthLabelStyle: {
fontSize: 16,
paddingVertical: 5,
color: "#000"
}
});
This might not be the optimal solution. If you have any doubts feel free to ask.
Hope this will helps you.
I've created a custom dropdown using TouchOpacity component of react native as follows.
<View style={dropDownStyle}>
<TouchableOpacity onPress={() => _switchTimeSpan('Day')}>
<Text style={dropDownItemStyle}>Day</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => _switchTimeSpan('Week')}>
<Text style={dropDownItemStyle}>Week</Text>
</TouchableOpacity>
</View>
The style is as follows.
dropDownStyle: {
position: 'absolute',
marginTop: 20,
width: 80,
},
dropDownItemStyle: {
marginTop: 5,
flex: 1,
textAlign: 'right',
},
When pressed the TouchOpacity component doesn't trigger the onpress function. This issue only exists in android and not IOS.
Edit 1 : There is a areachart created use react-native-svg-charts which is being overlapped by the mentioned dropdown. However upon inspecting if the reason for the onPress not working could be because of zIndex issues i noticed that the mentioned dropdown is the top most component.
The code for the chart is the following.
I am using react-native-svg-charts
<View style={containerStyle}>
<YAxis
data={data}
style={yAxisStyle}
formatLabel={value => yAxisFormat(value)}
contentInset={verticalContentInset}
numberOfTicks={5}
svg={axesSvg}
/>
<View style={chartWrapperStyle}>
<AreaChart
style={chartStyle}
data={data}
contentInset={verticalContentInset}
curve={shape.curveCatmullRom}
svg={{ fill: '#FF4D4D' }}
animate
/>
<View style={xAxisStyle}>
{
timeSpan !== 'Month' && (
<XAxis
data={data}
// formatLabel={(value, index) => months[value]}
formatLabel={(value, index) => xAxisPoints[index]}
contentInset={{ left: 10, right: 10 }}
// numberOfTicks={5}
svg={axesSvg}
/>
)
}
</View>
</View>
</View>
The style for the chart is as follows.
containerStyle: {
height: 200,
paddingLeft: 20,
paddingRight: 20,
flexDirection: 'row',
},
yAxisStyle: {
// marginBottom: 20,
position: 'absolute',
height: 180,
left: 20,
zIndex: 2,
},
chartStyle: {
flex: 1,
},
chartWrapperStyle: {
flex: 1,
},
xAxisStyle: {
marginHorizontal: -5,
height: 20,
},
When I'm testing this as isolated and only component on screen everything seems to work properly on Android (Samsung Galaxy Tab 2). Try to isolate this component and see if it will work for you on Android, maybe other components affect it. Also you could try to check if container component (with dropDownStyle) has some height or try to set 100%.
As I want to overlap this icon with two other Views, as shown in the image. this code is working on IOS platform but not on android. please suggest if there is any solution for Android.
var tabs = ['Activity', 'Files', 'People'];
this.state = {
tabs
};
return (
<Container style={{backgroundColor: '#F5F5F5'}}>
<View style={styles.topStrip}>
{
this.state.tabs.map((tab, index) => (
<View key={index} >
<TouchableOpacity>
<Text style={styles.streamName}>{tab}</Text>
</TouchableOpacity>
</View>
))
}
<View style={{position: 'absolute', backgroundColor: 'transparent', alignItems: 'center', justifyContent: 'center', zIndex: 5, elevation: 24, marginTop: 15, marginLeft: 300}}>
<EIcon size={40} color='#2196f3' name={'circle-with-plus'} />
</View>
</View>
<View style={{zIndex: -1}}></View>
</Container>
);
}
}
const styles = StyleSheet.create({
topStrip: {
alignItems: 'center',
},
streamName: {
marginTop: 7,
marginBottom: 6,
flexDirection: 'row',
alignSelf: 'center'
}
}
});
<View
style={{
paddingLeft: ITEM_HEIGHT * 3,
flex: 1,
position: "absolute",
top: 0,
right: 0,
bottom: 0,
left: 0,
zIndex: -1
}}
>
<Image
style={styles.centerCircle}
resizeMode="contain"
source={Images.ballSmall}
/>
</View>
In android, to use zIndex you need css with position-properties with top,left,right,bottom css
Tested On: Zenfone 3, Android 7, React Native 0.55.4
This issue is not caused by zIndex (although it does cause problem on Android).
Your icon is put inside the upper container view. React Native on Android does not support overflow: visible. That's why you see your icon being clipped outside the container.
You may put the icon on the "page" component level to solve this issue.
You may also refer to https://stackoverflow.com/a/50991892/6025730.
can't display floating button over webview on android.
ios work fine, on android doesn't show.
render function:
<View style={{ flex: 1}}>
<View style={{position:'absolute',right:0,marginTop:90,marginRight:10,zIndex:1,height:50,width:50}}>
<TouchableHighlight style={styles.addButton}
underlayColor='#ff7043' onPress={()=>{console.log('pressed')}}>
<Text style={{fontSize: 50, color: 'black'}}>+</Text>
</TouchableHighlight>
</View>
<WebView
source={require('./index.html')}
style={{marginTop:0}}
scalesPageToFit={Platform.OS !== 'ios'}
onMessage={this.onMessage}
postMessage={"Hello from RN"}
/>
</View>
css:
const styles = StyleSheet.create({
addButton: {
backgroundColor: '#ff5722',
borderColor: '#ff5722',
borderWidth: 1,
height: 100,
width: 100,
borderRadius: 50,
alignItems: 'center',
justifyContent: 'center',
position: 'absolute',
bottom: 20,
right:20,
shadowColor: "#000000",
shadowOpacity: 0.8,
shadowRadius: 2,
shadowOffset: {
height: 1,
width: 0
}
}
});
How can I display a button over web view on android ?
The solution is pretty simple, put the Button View code under/after the WebView code
<View style={{ flex: 1}}>
<WebView
source={require('./index.html')}
style={{marginTop:0}}
scalesPageToFit={Platform.OS !== 'ios'}
onMessage={this.onMessage}
postMessage={"Hello from RN"}
/>
<View style={{position:'absolute',right:0,marginTop:90,marginRight:10,zIndex:1,height:50,width:50}}>
<TouchableHighlight style={styles.addButton}
underlayColor='#ff7043' onPress={()=>{console.log('pressed')}}>
<Text style={{fontSize: 50, color: 'black'}}>+</Text>
</TouchableHighlight>
</View>
</View>
If for some reason you can't put it under the WebView, adding a elevation style prop higher than the WebView's, alongside the zIndex style prop will work for you.
That's because the zIndex property is quite broken on Android (see the dedicated issues). To compensate for it, you must invert the rendering order of your container's children.
This can be done either by rendering the button after the WebView:
<View style={{ flex: 1 }}>
<WebView />
<View style={{ styles.button }} />
</View>
Or by reversing the display order in your container, using flexDirection:
<View style={{ flex: 1, flexDirection: 'column-reverse' }}>
<View style={{ styles.button }} />
<WebView />
</View>
Note that you can also use the android-specific elevation API. This will act as a reliable z-index and is the only way to display a shadow on Android.
I am currently using React-Native for an Android Project. I have been trying to make a TextInput field with an icon beside the field. However, for some reasons, I notice that the flexDirection: 'row' is not working if the TextInput is one of its child component. The whole view of the one that I apply the style will automatically disappear. This is a snippet of how my code looks like:
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
<View style={{flexDirection: 'row'}}>
<Image
style={{height: 30, width: 30}}
source={require('./images/email-white.png')}
/>
<TextInput
style={{height: 40}}
underlineColorAndroid={'transparent'}
placeholder={'E-mail'}
placeholderTextColor={'white'}
onChangeText={(data) => this.setState({ username: data })} />
</View>
</View>
I also tried to wrap both component inside each individual view, but the problem still persists. Is there anyone who knows how to solve this? or anyone can confirm that this is a bug?
Your code with a small modification worked fine for me. The only thing I did was adding a width to the TextInput resulting in the icon being beside the text-input.
Working code:
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
<View style={{flexDirection: 'row'}}>
<Image
style={{height: 30, width: 30}}
source={require('./images/email-white.png')}
/>
<TextInput
style={{height: 40, width: 300}}
underlineColorAndroid={'transparent'}
placeholder={'E-mail'}
placeholderTextColor={'white'}
onChangeText={(data) => this.setState({ username: data })} />
</View>
</View>
I had the same problem when I was building example code from the book Mastering React Native
The code had enclosed a TextInput field in a View with a flexDirection: 'row' and the child TextInput field was not accessible. Only the TextInput border was visible. After playing around with some of the suggestions on this page I found something that worked.
If the container view has a flexDirection: 'row'. Please make sure to add a flex: 1 into your textfield input. The image flex does not seem necessary. As soon as I added the flex: 1 to the styles.input sheet, the TextInput was accessible.
The following code works for me :
<View style={globalStyles.COMMON_STYLES.pageContainer}>
<View style={styles.search}>
<Image
style={{height: 30, width: 30}}
source={require('../../images/email-white.png')}/>
<TextInput
style={styles.input}
onChangeText={text => this.setState({ searchText: text})}
value={this.state.searchText}
placeholder={'Search'}
placeholderTextColor={globalStyles.MUTED_COLOR}/>
</View>
</View>
Local Styles :
const styles = StyleSheet.create({
input: {
flex: 1,
height: 35,
color: globalStyles.TEXT_COLOR,
borderColor: globalStyles.MUTED_COLOR,
backgroundColor: globalStyles.BG_COLOR
},
search: {
borderColor: globalStyles.MUTED_COLOR,
flexDirection: 'row',
alignItems: 'center',
borderRadius: 5,
borderWidth: 1,
// marginTop: 10,
// marginBottom: 5
}
})
Global Styles (styles/global)
export const COMMON_STYLES = StyleSheet.create({
pageContainer: {
backgroundColor: BG_COLOR,
flex: 1,
marginTop: 0,
paddingTop: 20,
marginBottom: 48,
marginHorizontal: 10,
paddingHorizontal: 0
},
text: {
color: TEXT_COLOR,
fontFamily: 'Helvetica Neue'
}
});
Hopefully this provides assistance to you guys. It took me a long time get something this simple working.
Try closing your Image tag...
<Image style={{width:30, height: 30}} source={require('./icon.png')} />
Also, add some dimensions to your TextInput...
<TextInput style={{height: 40, borderColor: 'gray', borderWidth: 1}} />
You might also need to set flex: 0 on the image and flex: 1 on the TextInput