set tabbar icon color in react-native-navigation - react-native-navigation

Is there any way to dynamically set a new tab bar icon AND color?
In my app, I want the icon for the CHAT tab to be changed to red when a new message arrives.
Steps to Reproduce / Code Snippets / Screenshots
this.props.navigator.setTabButton(
{
tabIndex: 2,
screen: 'parkour.ChatListScreen',
title: 'Chat',
icon: iconsMap[2],
style: { color: 'red' }
},
the style property does not work at all, the resulting color is yellow.
I a using react native navigation v.1.

Updating BottomTabs items isn't possible in v1, but should be possible in v2.
Even though you're using v1, figured I'll post the solution for v2:
Navigation.mergeOptions(this.props.componentId, {
bottomTab: {
color: 'red',
icon: require('./someOtherIcon.png')
}
});
Where this.props.compoenntId is the componentId of your root screen. You can give screens predefined id's when declaring the layout and use that predefined id.

Add TabIcon component in navigationOption of createBottomTabNavigator
use redux or context api to change state of TabIconComponent.
navigationOptions: ({ navigation }) => ({
tabBarIcon: ({ tintColor }) => {// eslint-disable-line
const { routeName } = navigation.state;
let iconName;
if (routeName === 'Home') iconName = 'home';
else if (routeName === 'Notifications') iconName = 'notifications';
else if (routeName === 'Readout') iconName = 'readout';
else if (routeName === 'Inbox') iconName = 'messages';
else if (routeName === 'Profile') iconName = 'profile';
return <TabIcons iconName={iconName} tintColor={tintColor} />;
},
tabBarVisible: true,
}),

Related

Hyperlink on a Graphic element in ArcGis

i need your help please.
I would like to be able to click on a point added on an ArcGis map so that when I click on it I am redirected to another web page
I have been following the tutorials:
https://developers.arcgis.com/javascript/latest/display-a-map/
Display a map
Add a point
add a feature layer
Display a popup
This is the code so far:
require([
"esri/config",
"esri/Map",
"esri/views/MapView",
"esri/Graphic",
"esri/layers/GraphicsLayer",
"esri/layers/FeatureLayer"
], function(esriConfig,Map, MapView, Graphic, GraphicsLayer, FeatureLayer) {
esriConfig.apiKey = "YOUR_KEY";
const map = new Map({
basemap: "arcgis-topographic"
});
const view = new MapView({
container: "DivCarte",
map: map,
center: [-83.54500,19.02700],
zoom: 6
});
const graphicsLayer = new GraphicsLayer();
map.add(graphicsLayer);
const point = { //Create a point
type: "point",
longitude: -86.900000,
latitude: 21.201278
};
const simpleMarkerSymbol = {
type: "simple-marker",
color: [226, 119, 40], // Orange
outline: {
color: [255, 255, 255], // White
width: 1
}
};
const popupTemplate = {
title: "Cancun",
content: "<a href=http://travelwithnico.com>Site</a>"
}
const attributes = {
Name: "AttGraphic",
Description: "Ilalala"
}
const pointGraphic = new Graphic({
geometry: point,
symbol: simpleMarkerSymbol,
attributes: attributes,
popupTemplate: popupTemplate
});
graphicsLayer.add(pointGraphic);
I managed to open a popup showing the link but it opens on a new tab.
How can I force it to move to the link in the same window?
Thank you for your help.
Nico
Have you tried inlining a JavaScript inside an onclick event? Something like this:
...
content: 'Site'
...
I'm not sure if this will work, but it worths trying.

v-data-table button loading per row

Using vue v2.5 with vueCLI 3 trying to have a v-data-table that on each row have a button, when this button clicked should make it appear as loading.
v-btn has loading property by default, really I don't know why is not working...
<v-data-table
:headers="headers"
:items="records"
#dblclick:row="editRowCron_jobs">
<template v-slot:[`item.actions`]="props">
<v-btn color="blue-grey" :loading="props.item.createloading" fab dark small #click="ManuralRun(props.item)">
<v-icon dark>mdi-google-play</v-icon>
</v-btn>
</template>
</v-data-table>
On the click method, I can read but not set the item
export default {
data() {
return {
headers: [
{ text: "id", value: "id", align: " d-none" },
{ text: "actions", value: "actions" }
],
records: [] //grid rows filled by API
}
},
methods: {
ManuralRun(item){
this.records[2].createloading=true; //even I set it like that, nothing happens
item.createloading = true; //property changed here - ok
console.log(item); //here outputs the clicked item - ok
},
so, according to this
the property MUST pre-exist in the array, that means, when we get the result from the API, we have to add the property as:
this.records = data.data.map(record => {
return {
createloading: false,
...record
}
})

How to return back to previous screen from React StackNavigator to specific Tab

I am using React StackNavigator which has structure like this:
-----BottomNavigator
-------TabNavigator (has 3 screens)
---------StackNavigator
so I want to return to previous screen from stackNavigator to TabNavigator (screen 2).
Here is my code for TabNavigator:
const ServiceTabNavigator = createMaterialTopTabNavigator(
{
screenone: screenone,
screentwo: screentwo,
screenthree: screenthree
},
{
tabBarOptions: {
activeTintColor: "#1B5357",
inactiveTintColor: "gray",
style: {
backgroundColor: "#fff",
color: "#1B5357"
},
indicatorStyle: {
backgroundColor: "#1e90ff"
}
},
navigationOptions: {
tabBarLabel: "ESTH",
tabBarIcon: ({ tintColor }) => (
<Icon name="bars" color={tintColor} size={24} />
)
}
}
);
Here is for the StackNavigator which has code like this but it does not go to the screen2 instead screen1 of tabNavigator.
static navigationOptions = ({ navigation }) => ({
title: "Request Service",
headerLeft: (
<TouchableOpacity
onPress={() => {
() =>
navigation.dispatch(
NavigationActions.reset({
index: 0,
actions: [
NavigationActions.navigate({ routeName: "MainNavigator" }) //MainNavigator is bottomNavigator
]
})
);
navigation.navigate("screentwo");
}}
>
<Icon
name="times"
type="font-awesome"
iconStyle={{ color: "#000" }}
containerStyle={{ marginLeft: 16 }}
/>
</TouchableOpacity>
),
headerTitleStyle: {
color:'#00CA9D',
fontWeight: 'bold',
},
headerStyle: { borderBottomWidth:0 }
});
Thank you
I use react-navigator.. there is a property named jumpToIndex for this.
I solved it this way for my needs to open a Modal instead jumping to the given Tab.
Maybe you can modify to fit your needs:
<TabBarBottom
{...props}
jumpToIndex={(index) => {
if (index === 5) {
// This is the MORE-Tab-Button. Don't switch to tab, but open the Modal
props.navigation.navigate('Menu_Screen');
} else {
jumpToIndex(index);
}
}}
/>
From how you described your navigation hierarchy it looks like your root navigator is always Main/BottomNavigator, so why do you call dispatch reset before navigating to screentwo?
Seems like the issue might be that the reset action is not finished before you try to navigate to screentwo, so you end up on initialRoute of MainNavigator.
So calling just navigation.navigate("screentwo") (without reseting root) should do what you want to achieve.
In case you really need to reset the root, try executing the navigation to screentwo using dispatch as well, to make sure the actions are performed in sequence
const navigateAction = NavigationActions.navigate({
routeName: route,
params: params
})
navigation.dispatch(navigateAction)
OK after digging up I have found out the way
React NavigationV2 Way:
navigation.navigate('MainNavigator', {}, NavigationActions.navigate({ routeName: 'Requests' }))
React NavigationV3 Way:
navigation.navigate(NavigationActions.navigate({
routeName: 'MainNavigator',
action: NavigationActions.navigate({ routeName: 'Requests' })
}))
BottomNavigator as MainNavigator
Screentwo as Requests
In a nutshell navigation.navigate() has third parameter which acts likes second navigation.
So It first Navigate to MainNavigator ------then----> Screen2 in TabNavigator
Thanks to David check this post. Hope it will help someone else in future.
How to navigate between different nested stacks in react navigation

How to know the sideMenu visibility state

I have a topBar with a button that toggles the Side Menu.
I have registered a navigationButtonPressed action as below
navigationButtonPressed({ buttonId }) {
switch (buttonId) {
case 'sideMenuButtonId':
Navigation.mergeOptions(this.props.componentId, {
sideMenu: {
left: {
visible: true
}
}
});
break
default:
break
}
}
But in this case, the button only makes the sideMenu visible, and Im trying to use it so it toggles the menu open and closed.
So i replaced the above with a variable approach seen below..
var sideMenuVisible = false
navigationButtonPressed({ buttonId }) {
switch (buttonId) {
case 'sideMenuButtonId':
sideMenuVisible = !sideMenuVisible
Navigation.mergeOptions(this.props.componentId, {
sideMenu: {
left: {
visible: sideMenuVisible
}
}
});
break
default:
break
}
}
Which works fine if the user only uses the button to open and closed the sideMenu, but the user can also open/close the menu by swiping to open the menu as well as tapping out the menu to close it.
Is there a way to check the visibility of the sideMenu so I can properly use an action to open/close the menu on command?
It can done much more simple.
Think you should create it as a state, because the component have to know, it should be rerendered, when the state change.
So something like
state = { isOpen: false };
toggleSidebar = () => {
this.setState({ isOpen: !isOpen })
}
And now, you should call the toggleSidebar function when you click the button

VirtualScroll (List) with dynamic item height scrolling not smooth and jumping

I have been tuning the VirtualScroll (List) component for almost whole day but no luck.
I'm building a web based chatting application in which uses the react-virtualized List to display the chatting messages. Since message may have different content and different height, I use react-measure to calculate the item height and issue the recomputeRowHeights in rowRenderer.
The result is bad, VirtuallScroll List will jump around whenever I stopped the scrolling. For example, when I scrolled to the half of browser, I should see the middle of the messages, but it always suddenly shift the offset. Please take a look at the recorded video:
https://drive.google.com/file/d/0B_W64UoqloIkcm9oQ08xS09Zc1k/view?usp=sharing
Since I only use the List and Autosizer component, I only adapt the required css file into my project which is like
```
.VirtualScroll {
width: 100%;
outline: none;
}
```
For the render method, I nested a lot of flex components inside the rowRender:
Here is the code:
```
render() {
const inChat = this.context.store.getState().inChat;
const {conversationList} = this.state;
const imgUrl = 'img/builtin-wallpaper-1.jpg';
const backgroundStyle = {
backgroundImage: 'url(' + imgUrl + ')',
backgroundRepeat: 'no-repeat',
backgroundSize: 'cover',
backgroundPosition: 'top left'
};
if (inChat.id === this.id && inChat.status === 'FETCHING'){
return (
<Box column center height="80%">
<CircularProgress />
</Box>
);
} else if (inChat.id === this.id && inChat.status === 'FETCHED'){
return (
<Box column flex="1 0 100%" style={backgroundStyle}>
<HorizontalToolBar/>
<AutoSizer disableHeight={true}>
{({ width }) => (
<List
ref={(element) => {this.VirtualScroll = element;}}
className='VirtualScroll'
height={window.innerHeight - toolbarHeight - textAreaHeight}
overscanRowCount={10}
noRowsRenderer={this._noRowsRenderer.bind(this)}
rowCount={conversationList.length}
rowHeight={i => {
return (Measured_Heights[i.index] | 20); // default Height = 58
}}
rowRenderer={this._rowRenderer}
scrollToIndex={undefined} // scroll to latest item
width={width}
/>
)}
</AutoSizer>
<InputControl chatId={this.id} sendChatText={this._sendChatText.bind(this)}/>
</Box>
);
} else {
return null;
}
}
_rowRenderer ({ index, key, style, isScrolling }) {
console.log(Measured_Heights);
const rowData = this._getDatum(index);
// let renderItem;
// console.log('index = ' + index + ' key = ' + key);
if (rowData.type == 'conversation') {
if (rowData.data.type == netModule.TYPE_SYSTEM) {
// system message
return (
<Measure key={key} onMeasure={(dims) => this._onMeasure(index, dims)}>
<SystemMessage data={rowData.data}/>
</Measure>
)
}
if (rowData.data.senderId == this.state.selfProfile.username) {
// outgoing message
return (
<Measure key={key} onMeasure={(dims) => this._onMeasure(index, dims)}>
<RightMessage
screenWidth={(window.innerWidth - leftToolBarWidth) / 2 }
screenHeight={window.innerHeight - toolbarHeight}
data={rowData.data}/>
</Measure>
);
} else {
// incoming message
// append userProfile to left messages
return (
<Measure key={key} onMeasure={(dims) => this._onMeasure(index, dims)}>
<LeftMessage
userId={rowData.data.senderId}
userProfile={this.state.groupUserProfiles[rowData.data.senderId]}
screenWidth={(window.innerWidth - leftToolBarWidth) / 2 }
screenHeight={window.innerHeight - toolbarHeight}
data={rowData.data}/>
</Measure>
);
}
}
}
```
I read a couple docs that Flexbox may be intercept the scrolling event, but even though I added overflow-y: hidden to nested component I didn't see the issue disappear. Have you ever seen this wrong scrolling behavior with List component before?
Any suggestion is welcome.
I can't see the video, but I think I had something similar recently. From what I can see, you're not making use of the style parameter passed into your _rowRenderer method. This parameter contains some CSS transforms that make the row appear at the right vertical position in the scrolling list.

Resources