I crated a tab view using TabNavigator. Here is the library I used. Total I have 3 tabs. So Initial tab is loading & rendering fine without hassle. But the problem is coming with 3rd Tab. I checked with console.log() in every method in that 3rd tab component. Every method is executing but not showing results ( Showing blank screen) until I interact with it. When I start interacting with it, then only data is re-rendering(I think so).
How can I solve this problem? Any help?
Thanks
I solved it by configuring tab navigator with prop lazy true. Below is the code I modified. It's working now.
const TabView = TabNavigator({
feed: { screen: Feed },
info: { screen: Info },
members: {screen: Members}
}, {
tabBarPosition: "top",
tabBarOptions: {
activeTintColor: "#4A90E2",
inactiveTintColor: "#4A4A4A",
style: {
backgroundColor: 'white',
height:56,
alignItems: 'center',
shadowColor: '#000000',
shadowOpacity: 0.1,
shadowRadius: 0,
shadowOffset: {
height: 2,
width: 1
}
},
tabStyle: {
height: 40,
},
labelStyle: {
fontSize:12,
fontFamily:'HelveticaNeue-Medium'
}
},
lazy:true
});
Related
I am using the default stack from react navigation, and in my navigator screen options I have my own custom header header: (props) => <Header props={props} />. In my screen, I have a background colour, and in my SafeAreaView I have a background colour. For illustration I have set them both to the same.
In my custom header I am applying margin of 15 horizontally as well as to the top. So it is the colour underneath the custom header.
My question is this: Where is this header background colour being set? (the light grey one)
Here you can see what I mean
I have tried headerStyle {backgroundColor}, but no difference (i believe because using header overrides a lot of these options? Unsure though as it is not stated in the documentation.)
For reference, I am basing it off of this documentation: https://reactnavigation.org/docs/native-stack-navigator/#options
However it appears that this background colour is being set somewhere else entirely? And so I'm not sure where.
I realize setting headerTransparent and applying margin for each screen is a viable solution but I figure there is a better way to simply set the background colour of this space correctly.
edit with header component:
export default function Header({ props }) {
const { navigation, route, options, back } = props;
const title = getHeaderTitle(options, route.name);
return (
<View style={styles.header}>
<View style={styles.container}>
{back && (
<IconButton
type="ion"
name="chevron-back"
size={26}
iconStyle={styles.backButton}
onPress={navigation.goBack}
/>
)}
<Text style={styles.title}>{title}</Text>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
width: screenWidth - 30,
height: 60,
borderRadius: 10,
padding: 15,
marginTop: 15,
backgroundColor: colors.white,
alignSelf: "center",
flexDirection: "row",
alignItems: "center",
},
backButton: {
zIndex: 1,
},
title: {
flex: 1,
textAlign: "center",
flexDirection: "column",
fontSize: 24,
fontWeight: "bold",
// marginLeft: -26,
},
header: {
backgroundColor: colors.neutral95,
},
});
I want to have a text s.calculatedQuantity and next to it an icon. But i want them to be always next to each other and not be separated. Sometimes when s.setDescription is long i have a bad result like in the image below. And i dont know why there is sometimes that space between the icon and the text s.calculatedQuantity. Can someone explain to me that ?
.
I Have my code like this :
function generateSetDescription(s, picto) {
return {
columns: [
{
text: `${s.setDescription} - `,
fillColor: '#000',
color: '#FFF'
},
{
text: `${s.calculatedQuantity}`,
fillColor: '#000',
color: '#FFF'
},
{
image: icon,
width: 10,
height: 10,
fillColor: '#000',
},
]
}
}
The problem you're having seems to be caused by too long words (not text) normal text seems to wrap correctly when a blank space is found.
My suggestion is to programmatically break your 'very long words' adding a - in between.
something like this should work in your case
const text = veryLongTextWithLongWords;
const wrappedText = text.split(' ').map(word => {
if(word.length > 80){
return `${word.substr(0, 40)}-${word.substr(41)}
}
return word;
})
const columns = [
{ text: wrappedText }
]
You can test it out here
http://pdfmake.org/playground.html
I'm using react-navigation with StackNavigator. Is there a way to avoid the overlapping of the back button label and the headerTitle by truncating the back button label?
const MainNavigationOptions = {
headerStyle: {
backgroundColor: colors.CiPrimary
},
headerTitleStyle: {
color: 'white',
height: 50,
width: 140
},
headerTintColor: 'white',
headerTitle:
<Text>LONG TEXT FOR TESTING</Text>
}
Illustration of issue:
(This Answer takes into account that the viewer is using react-navigation 5.x)
In Your Screen component
export const screenOptions = (navData) => {
let title = navData.route.params.movieTitle;
if (title.length > 18) {
title = title.substr(0, 18) + "...";
}
return {
headerTitle: title,
};
};
Here, since we are using substr() , you can use it accordingly and truncate it to custom match your case, keeping in mind the edge cases.
Then you can import it in your AppNavigator.js or wherever you initialize your navigator (in my case below ;)
import {screenOptions as MoviesDetailScreenOptions} from
"../screens/MovieDetailScreen";
Here screenOptions is the named-export you are using MoviesDetailScreenOptions is the alias if i am not mistaken.
Create a style for your button label because it now left for you to style it your self and you can style it any way you want.
const styles = {
leftTouch: {
flexDirection: 'row',
...
},
customStyle: {
paddingLeft: 10,
...
}
textStyle: {
width: 60,
fontSize: 14,
......
}
}
const { leftTouch, customStyle, textStyle} = styles;
Instead of Icon you can use <Image /> but am assuming you are using an icon i.e react-native-vector-icon or likes.
N.B Now you have control of everything the button should do especially when pressed.
const MainNavigationOptions = {
headerStyle: {
backgroundColor: colors.CiPrimary
},
headerTitleStyle: {
color: 'white',
height: 50,
width: 140
},
.....
headerLeft: ( <TouchableOpacity style={leftTouch} onPress={() => goBack()} >
<Icon name="ios-arrow-dropleft-circle-outline" size={25} style={customStyle} color="#ffffff" />
<Text numberOfLines={1} style={textStyle}>A Longer Text for testing</Text>
</TouchableOpacity>
)
}
If you mean to shorten the back button label, why not use either:
headerBackTitle (change the Back label for the previous screen, put it in navigationOptions of the previous screen);
headerBackTitleStyle (change the Back label displayed on current screen, put it in navigationOptions of the current screen)
I'm working on a little app which uses Sencha Touch 2 for the user interface. Right now I'm running it in Safari on my iPad and iPhone.
My problem is that whenever I tap a text field, Safari brings up the virtual keyboard and pushes the whole web view upwards, off the screen.
This doesn't look very natural, since the top-toolbar is not visible anymore.
Here are two screenshots which demonstrate the problem.
In the second screenshot you can see the effect when the keyboard is visible.
Is there a way to prevent this behavior, and have Safari resize the user interface instead?
Unfortunately, Apple wants this behavior, but someone suggested a little hack using window.scrollTo():
listeners: {
focus: function() {
window.scrollTo(0,0);
}
}
Putting this code in launch function in app.js worked for me:
if (Ext.os.is.Android) {
Ext.Viewport.on('painted', function () {
Ext.Viewport.setHeight(window.innerHeight);
});
}
if (Ext.os.is.iOS) {
Ext.Viewport.on('painted', function () {
Ext.Viewport.setHeight(window.innerHeight);
});
}
I have found a solution that works for me.
You move the topbar into the container.
xtype: 'container',
docked: 'top',
height: '100%',
html: '',
itemId: 'MyContainer',
width: '100%',
items: [
{
xtype: 'titlebar',
docked: 'top',
itemId: 'topBar',
title: 'Obec Webchat',
layout: {
type: 'hbox',
align: 'start'
},
items: [
{
xtype: 'button',
action: 'back',
id: 'BackButton',
itemId: 'BackButton',
margin: '5 70% 5 15',
ui: 'back',
text: 'Home'
}
]
},
{
xtype: 'container',
docked: 'bottom',
height: '95%',
html: '<iframe src="http://webim.obec.local/" width="100%" height="100%" scrolling="yes"></iframe>',
itemId: 'MyContainer1',
width: '100%'
}
]
}
Hope this helps.
You will need to call the blur() method on textfield
// Assuming the id of textfield - "textFieldId"
Ext.getCmp('textFieldId').blur();
Attempts to forcefully blur input focus for the field.
If you this using html into Sencha elements must remove something tag html. Or can you put tag in the source html code. I hope help you. :)
I am trying to add an option to a profile page for twitter widget and I have a field where users can add their twitter accounts and below it shows a preview of the widget. It works fine if I enter an account and click save and come back. But what I am trying to do is make it dynamic, to refresh the widget with corresponding account when blur event occurs on the text-field.
I have the following code:
var twitterWidget = new TWTR.Widget({
version: 2,
type: 'profile',
rpp: 4,
interval: 6000,
width: 'auto',
height: 300,
theme: {
shell: {
background: '#cccccc',
color: '#333333'
},
tweets: {
background: '#ffffff',
color: '#333333',
links: '#0099cc'
}
},
features: {
scrollbar: false,
loop: false,
live: false,
hashtags: true,
timestamp: true,
avatars: true,
behavior: 'all'
}
});
twitterWidget.setUser(twitterUser).render().start();
$('#twitter_widget_id').change(function(){
twitterWidget.setUser($(this).val()).render().start();
});
In this case it works wrong: it shows only the newest tweets from all the accounts that I entered and in general I'm getting an empty widget.
If I delete the object and create a new one it makes the page blank and then adds the widget.
Does anyone know some public methods for the TWTR.Widget() like re-render() or something like that?
Thanks.
The documented Twitter widget source code is available at http://twitter.com/javascripts/widgets/widget.js and reading through it will tell you everything you need to know about how to manipulate its behavior. Briefly, the widget works like this:
When the widget is first created with new TWTR.Widget it calls .init() and takes note of where it's embedded in the page, inserting the widget HTML code into the DOM at that position. (It always assumes you're embedding, which is why if you create a new widget in a head script or in the context of the window it will end up embedding itself in the root of the window.)
But, you can still create the widget using a function (as long as it's called from the embedded script) and then hold onto a reference to the widget for later. When you call .render() later the widget just re-renders itself wherever it happens to be.
There are some pseudo-private methods on the TWTR object that you might try for fun, such as _getWidgetHtml() - which is called by .render() but you shouldn't need to use those.
I just wrote the following code, and it works well for me. Call this function from your embedded script (as shown), then call it again later with a new search parameter to re-render it.
<div id="my_widget_region">
<script src="http://widgets.twimg.com/j/2/widget.js"></script>
<script>do_twitter_widget('"#winning" or "justin bieber"');</script>
</div>
function do_twitter_widget(search_query, title, subtitle) {
if (!window.widgetRef) {
window.widgetRef = new TWTR.Widget({
version: 2,
type: 'search',
search: search_query,
interval: 6000,
title: title || 'Tweets related to',
subject: subtitle || search_query,
width: 'auto',
height: 500,
theme: {
shell: {
background: '#8EC1DA',
color: '#FFFFFF'
},
tweets: {
background: '#FFFFFF',
color: '#444444',
links: '#1985B5'
}
},
features: {
scrollbar: false,
loop: true,
live: true,
hashtags: true,
timestamp: true,
avatars: true,
behavior: 'default'
},
ready: function() {
// when done rendering...
}
});
window.widgetRef
.render()
.start();
}
else {
if (search_query != window.old_twitter_search) {
window.widgetRef
.stop()
.setSearch(search_query)
.setTitle(title || 'Tweets related to')
.setCaption(subtitle || search_query)
.render()
.start();
}
}
window.old_twitter_search = search_query;
return window.widgetRef;
}
You can just reload the widget by create a new instance using "id" params as html id of the the widget element.
Exemple below. (Works fine for me)
window.twitterCreateOrUpdateProfile = function (username) {
var opts = {
version: 2,
type: 'profile',
rpp: 4,
interval: 30000,
width: 298,
height: 320,
theme: {
shell: {
background: '#86b9d1',
color: '#ffffff'
},
tweets: {
background: '#ffffff',
color: '#444444',
links: '#0b0d0d'
}
},
features: {
scrollbar: true,
loop: false,
live: false,
behavior: 'all'
}
};
if (window.twitterCreateOrUpdateProfile.instance) {
opts.id = window.twitterCreateOrUpdateProfile.instance.widgetEl.id;
}
window.twitterCreateOrUpdateProfile.instance = new TWTR.Widget(opts);
window.twitterCreateOrUpdateProfile.instance.render().setUser(username).start();
}
window.twitterCreateOrUpdateProfile('evaisse');