The problem is pretty simple, still I can't figure out why it happens. I'd need some good Android and/or React Native developers.
I have a settings page in my application which renders 4 boxes (depending content of the settings, like user password, email modification...) and one of them has a bit much more content than the others.
The problem seems to only occur on Android 7.0 (testing with a real device, Honor 8) and it works well on One Plus 6 (8.1) and a Xiaomi (I don't know which one, running 7.1)
As long as I want to display all the content of the box, it will just not render to the screen, but still takes the height needed in the ScrollView to be displayed (see the screens)
At first, I didn't understand why, because no error was triggered, I decided to check the logCats and I got this error :
View: ReactViewGroup not displayed because it is too large to fit into a software layer (or drawing cache), needs 8636760 bytes, only 8294400 available
Imgur
So I tried multiple things:
set android:hardwareAccelerated="false" in the AndroidManifest, this solution works BUT the app is quite laggy when you scroll, and all is a bit slowed down (I would love to avoid this)
Delete some components from the render, which also works, but... obviously, I want all my content in this box
I tried to understand which component takes a lot of space (in bytes) by adding/deleting the components in the view and referring to the logCat, seems like ZestInput takes quite a lot, as custom components for Toggles, and Checkboxes (I also tried with native TextInput to compare with our custom input, the result was not that far... they bot take a lot of space)
render() {
const {
textStyle,
titleTextStyle,
subtleText,
boxStyle,
marginLarge,
marginSmall,
marginLeft,
buttonStyle,
} = styles;
const { isUpdating, newMail } = this.state;
const { user, emailEdition } = this.props;
const emailTranslation =
newMail === ''
? translations.t('ADD_EMAIL')
: translations.t('CHANGE_EMAIL');
return (
<MCollapsableBox
style={boxStyle}
headerText={translations.t('APPLICATION_SETTINGS')}
>
<View>
<Text style={[titleTextStyle, marginLarge]}>
{translations.t('PARAMETERS_CHOOSE_LANGUAGE')}
</Text>
{(newMail === '' || emailEdition) && (
<View>
<Separation />
<Text style={[titleTextStyle, marginLarge]}>
{translations.t('EMAIL')}
</Text>
<ZestInput
//ref={ref => (this.inputRef = ref)}
placeholder={emailTranslation}
onChangeText={this.changeMailAddress}
value={newMail}
/>
{user.tmpEmail !== '' && (
<View>
<Text style={[textStyle, marginSmall]}>
{translations.t('CURRENT_TMP_MAIL')}
</Text>
<Text style={[textStyle, marginLeft]}>{user.tmpEmail}</Text>
<Text style={[subtleText, marginLeft]}>
{translations.t('EMAIL_NEEDS_VALIDATION')}
</Text>
</View>
)}
<PrimaryButton
onPress={this.onChangeEmail}
style={buttonStyle}
isLoading={isUpdating}
disabled={!this.checkIsEmail(newMail)}
>
{emailTranslation}
</PrimaryButton>
</View>
)}
<Separation />
<Text style={[titleTextStyle]}>
{translations.t('PARAMETERS_VISIBILITY')}
</Text>
{_.map(this.state.privacyOptions, (value, key) => {
return (
<TitledTextToggle
title={value.text}
options={value.options}
onPress={this.toggleChanged}
key={key}
id={key}
/>
);
})}
<Separation />
<Text style={[titleTextStyle, marginSmall]}>
{translations.t('MOOD_NOTIFICATIONS_SETTINGS')}
</Text>
<Text style={[textStyle, marginLarge]}>
{translations.t('MOOD_NOTIFICATIONS_SETTINGS_TEXT')}
</Text>
<CheckboxList
onPress={this.onPressCheckbox}
options={this.state.moodNotification}
/>
<PrimaryButton
onPress={this.onSave}
style={buttonStyle}
isLoading={isUpdating}
>
{translations.t('SAVE')}
</PrimaryButton>
</View>
</MCollapsableBox>
);
}
This is what I expect
Imgur
Imgur
Imgur
Related
I am working on a settings screen design for this startup and am very new to react native. I am an intern, but I am trying to add lines between each button. I'll attach a screenshot of what it should kind of look like, but I just am lost with no matter how much I look up, I can't find something that will work for me.
So far what I did was:
<View className="w-full mt-2 mb-7 flex-row">
<TouchableOpacity onPress={() => navigation.navigate(RouteName.home)} className="flex flex-row items-center space-x-3 w-24">
<Ionicons name='person-sharp' size={24} color="grey"></Ionicons>
<Text>Profile</Text>
<AntDesign name='right' size={24} color='#7A7A7A' style={{position: 'absolute', right: 0}}></AntDesign>
</TouchableOpacity>
</View>
I dont have a specific stylesheet connected to it other than the inline one.
I attached a picture of what it should look like, but I am mainly struggling on the line between each button.
How can I show Read more button in Text if text length exceeds more than 2 lines? On Click of that Read more button a custom popup will be shown where full text will be visible. I have searched and checked here, here, here, but didn't found any proper solution to show Read more button as per requirement.
I tried this solution attached.. But here if I fixes numberOfLines to a value then "e.nativeEvent.lines.length" returns fixed value and if don't fixes numberOfLines then it returns complete text with ReadMore button which is wrong.
const ReadMore = props => {
const [showMore, setShowMore] = useState(false)
const longText = 'Nature, in the broadest sense, is the natural, physical, or material world or universe. "Nature" can refer to the phenomena of the physical world, and also to life in general. The study of nature is a large, if not the only, part of science. Although humans are part of nature, human activity is often understood as a separate category from other natural phenomena.'
return (
<View style={{
margin: 20,
}}>
<Text
numberOfLines={2}
onTextLayout={(e) => setShowMore(e.nativeEvent.lines.length > 2)}
>{longText}</Text>
{showMore && (
<Text style = {{color: 'blue'}} onPress = {() =>{
//Read more text action
}}>Read More...</Text>
)}
</View>
)
}
I am doing a dictionary app with lists of items like this:
acceptable, benevolent, big, charitable, considerate
fair, good, helpful, honest, hospitable
lavish, reasonable, thoughtful, tolerant, unselfish
Each item in the list is a link which leads to the similar list related to the word clicked.
I have two questions:
How to do it in React Native w/o falling into caring hands of React Native WebView? It's required to support styling (as in picture) and handling targeted clicks somehow.
Alternative solutions are welcome, including those built upon the WebView component. Just to consider performance side in here.
P.S. I have spotted alike functionality in the M.-W. dictionary app:
According to doc:
Text supports nesting, styling, and touch handling.
So I think the best solution is to properly nest your texts and pass them a function to handle the onPress action.
I will give an example code, not styled at all but completely stylable:
onPress = (text) => {
// do stuff
return
}
render() {
return (
<View style={styles.container}>
<Card>
<Text>
Synonyms:
{this.state.synonyms.map(synonym => {
return <Text onPress={() => this.onPress(synonym)}> {synonym} </Text>
})}
</Text>
</Card>
</View>
);
}
And here is a snack if you wanna take a look
I'm using a FlatList with 2 columns, it works fine except in few rows, it takes the complete row, instead of half of it. I have this issue both in Android and iOS. I tried raising an issue in Flatlist Github but was of no use - https://github.com/facebook/react-native/issues/19156#issuecomment-387200626
<FlatList
vertical
numColumns={2}
extraData={this.state}
data={this.state.bikeCities}
style={styles.CityListView}
showsVerticalScrollIndicator={false}
keyExtractor={(item, index) => index.toString()}
renderItem={({item:rowData, index}) => {
if(rowData.country_id == this.state.selectedCountryId)
{
return(
<TouchableOpacity style={styles.FlatListStyle}
onPress={() => this.props.citySelection(rowData,
this.state.selectedView)}>
<Text style={styles.cityText}> . {rowData.name}</Text>
</TouchableOpacity>
);
}
}}/>
Here is the screenshot of obtained result -
Screenshot
Anybody can help me out with this issue?
The issue in your code is that you are conditionally rendering the row item, I think the blank that you are seeing on the list is because the condition didn't meet for those items
if (rowData.country_id == this.state.selectedCountryId)
If you need to render item based on some selection, then preprocess / filter the data beforehand and then pass to FlatList.
Hope this will help!
I have a problem using TouchableOpacity with the code below.
when I press and release "Button 1" the opacity takes a few seconds to return to normal; besides, it seems the rendering of whole app is halt, because if I rotate my device, the screen does not get re-layout until a few seconds later.
but if I press and release "Button 2", the opacity returns to normal immediately.
Would anyone please let me know what should I do to solve this?
Thanks.
class someComponent extends Component {
buttonPressed() {console.log(arguments);}
render() {
// something
return (
<View style={styles.container1}>
<TouchableOpacity onPress={this.buttonPressed}>
<Text style={styles.button}>Button1</Text>
</TouchableOpacity>
<TouchableOpacity onPress={()={console.log(arguments);}}>
<Text style={styles.button}>Button2</Text>
</TouchableOpacity>
</View>);}
devices used for testing: Samsung GSII: Android 4.1.2, (some tablet): Android 4.1.1