oblador / react-native-vector-icons

Customizable Icons for React Native with support for image source and full styling.
https://oblador.github.io/react-native-vector-icons/
MIT License
17.45k stars 2.12k forks source link

Using vector icons in navicon of toolbarAndroid #101

Closed ssh-randy closed 8 years ago

ssh-randy commented 8 years ago

So question, I'm trying to use the "bars" icon from fontAwesome in my toolbarAndroid component, but can't seem to get it working. How would I use an icon for navbar? I saw a similar issue, do I have to convert the vector icon into an image in order to do that? If I do that, what will happen to the sizing of the image?

oblador commented 8 years ago

Yes you'd need to convert it to an image with Icon.getImageSource. However my last explorations into this yielded that ToolbarAndroid doesn't suport this yet. Superficially it should, so not sure why not.

But haven't tried with the latest release, please give it a try, reply with your results and I'll update the README.

ssh-randy commented 8 years ago

hmm... so i'm a noob with js, so bare with me, but I tried this:

componentWillMount: function() { Icon.getImageSource('bars', 30, 'white').then((source) => this.setState({ barsIcon: source })); },

and in my render function this... <ToolbarAndroid style={styles.toolbar} navIcon= {this.state.barsIcon} actions={[{title: 'Settings', show: 'always'}]} onActionSelected={this.props.openDrawer} >

and it gave me an error saying I was passing a null into navIcon. My guess is that it waits for the component to mount before setting the barsIcon state, so when the toolbarAndroid initially renders the state is null, and most likely toolbarAndroid doesn't support having something as null. Is there a way to have a static image for the toolbar? Or is the solution to have an if statement on rendering, such that if the component hasn't mounted yet, we just don't render the navIcon until it is rendered?

oblador commented 8 years ago

The solution, like you suggest, is to not render the ToolbarAndroid until this.state.barsIcon is populated. It's fairly quick, but it will be slower than the first render() call.

ssh-randy commented 8 years ago

got it. trying it out now!

ssh-randy commented 8 years ago

hmm... i have this:

var toolbarAndroid;
if (this.state.barsIcon !== false) {
  toolbarAndroid = <ToolbarAndroid
                    style={styles.toolbar}
                    navicon={this.state.barsIcon}
                    actions={[{title: 'real', show: 'always'}]}
                    onActionSelected={this.props.openDrawer} >
                  </ToolbarAndroid>;
} else {
  toolbarAndroid = <ToolbarAndroid
                    style={styles.toolbar}
                    navicon={menuImage}
                    actions={[{title: 'fake', show: 'always'}]}
                    onActionSelected={this.props.openDrawer} >
                  </ToolbarAndroid>

}

along with the getImageSource in componentWillMount. However, nothing is showing up for the navicon. going to try to do some more debugging... but looks like I'll probably have to just write my own toolbar :S

ssh-randy commented 8 years ago

ah i had navIcon misspelled. after correcting the spelling... i get "error while updating property 'navIcon' of a view manage by: ToolbarAndroid"

ssh-randy commented 8 years ago

final code is this:

var toolbarAndroid; if (this.state.barsIcon !== false) { toolbarAndroid = <ToolbarAndroid title="TITLE" titleColor='white' style={styles.toolbar} navIcon={this.state.barsIcon} actions={[{title: 'real', show: 'always'}]} onActionSelected={this.props.openDrawer} > ; } return (

{toolbarAndroid} and i get "error while updating property 'navIcon' of a view managed by: Toolbar Android" seems like it still doesn't work for toolbarAndroid... no idea why though
oblador commented 8 years ago

Yeah, that's where I landed as well. I guess one of us ought to get into the code for that component in React Native core and fix that issue.

ssh-randy commented 8 years ago

how hard do you think it'll be to fix? i'm pretty new to react native (and javascript in general), i can try taking a quick look but I don't know if I'd be much good haha :)

oblador commented 8 years ago

Don't know, please take a look :-) I'm currently tied up at work and don't use Android myself.

ssh-randy commented 8 years ago

haha alright, i'll give it my best effort! but I'm trying to roll something out, so worst case i might just try to not use navIcon if I can't find anything in a couple of hours.

ssh-randy commented 8 years ago

hmm weird... I actually gave your code another shot like such:

componentWillMount: function() { Icon.getImageSource('bars', 30, 'white').then((source) => this.setState({ barsIcon: source })); },

...

if (this.state.barsIcon !== false) {
  //var image = <Image source={this.state.barsIcon} />;
  toolbarAndroid = <Image source={this.state.barsIcon} style={styles.toolbarButton} />;
} else {
  toolbarAndroid = <ToolbarAndroid
                    title="TITLE"
                    titleColor='white'
                    navIcon={require('./assets/hamburger_menu.png')}
                    style={styles.toolbar}
                    actions={[{title: 'fake', show: 'always'}]}
                    onActionSelected={this.props.openDrawer} >
                  </ToolbarAndroid>

}

and when it rendered toolbarAndroid, the icon did not show. Wondering if there is something else wrong with my code, or if android doesn't properly call getImageSource

oblador commented 8 years ago

@cabooserwar: can you show me the toolbarButton style?

ssh-randy commented 8 years ago

toolbarButton: { width: 45, height: 45, },

this is all i had (i had other things but I took them out, I actually tried it without any styling too)

Mokto commented 8 years ago

This is what I did

import React, { Component,View, ToolbarAndroid } from 'react-native';
import Icon from 'react-native-vector-icons/MaterialIcons';

export default class NavBar extends Component {
  constructor(props) {
    super(props);
    this.state = {
      icon: null
    }
  }
  componentWillMount() {
    Icon.getImageSource('android', 20, 'red').then((source) => this.setState({ icon: source }));
  }
    render() {
      const { icon } = this.state;

      if(!icon) return null;

      return (
        <View style={styles.container}>
          <ToolbarAndroid
            navIcon={icon}
            style={styles.toolbar}
            title="Title" titleColor="white" />
        </View>
      );
    }
}

But I got this error : Error while updating property navIcon of a view managed by : ToolbarAndroid.

I do not know if it helps but I'm stuck with this error too :+1:

rkostrab commented 8 years ago

I am facing the same problem. I've also created a stackoverflow thread. If you want to keep using pixel perfect ToolbarAndroid then you have to create and use static images.

alexbepple commented 8 years ago

Right now, it's not supposed to work, if I read the docs correctly:

Although the Toolbar supports remote images for the logo, navigation and action icons, this should only be used in DEV mode where require('./some_icon.png') translates into a packager URL. In release mode you should always use a drawable resource for these icons. Using require('./some_icon.png') will do this automatically for you, so as long as you don't explicitly use e.g. {uri: 'http://...'}, you will be good. – https://facebook.github.io/react-native/docs/toolbarandroid.html, emphasis added

But that's exactly what react-native-vector-icons does: setting an uri.

oblador commented 8 years ago

@alexbepple: actually {uri: 'http://...'} is supported (although discouraged), whereas local file paths are not it seems unless served the packager way. Maybe the only way forward is to subclass ToolbarAndroid.

oblador commented 8 years ago

Since https://github.com/facebook/react-native/commit/142f8c92de22a27bcbf09d8a0626a562c67a6aff is now released in 0.21 I can now happily announce ToolbarAndroid support in 1.3.2.

apastel commented 8 years ago

Was super excited to hear this and I definitely appreciate the updates, but icons are still not rendering for me in my Toolbar.

I'm following the exact example under the ToolbarAndroid heading in the README.

The first error I get is: Error while updating property 'navIcon' of a view managed by: ToolbarAndroid

After commenting out the navIconName property, I then get a different error: Error while updating property 'overflowIcon' of a view managed by: ToolbarAndroid

After commenting out the overflowIconName property, there are no longer any errors. However, the icons specified in the actions property (i.e. gear-a and social-twitter) are not rendering in the toolbar and I see the title text instead.

I can confirm that the same icons will render perfectly if done outside ToolbarAndroid in a separate element like so: <Icon name="gear-a"/>

An npm ls shows that I'm running react-native@0.21.0 and react-native-vector-icons@1.3.2, and I've re-ran react-native run-android and restarted the packager several times, as well as clearing all my watches. I'm not sure what else to try. Not sure if anyone else is having this issue.

oblador commented 8 years ago

@apastel: Did you run react-native upgrade?

oblador commented 8 years ago

Also did you fully integrate?

apastel commented 8 years ago

Yes to fully integrating, no to running react-native upgrade. Going through that process now, I'll let you know. Thanks.

apastel commented 8 years ago

Nope, still get the same errors and then no icons rendering in the toolbar. Really confused. <Icon.Button> works fine as well.

After upgrading react-native I used rnpm link and verified I have the correct lines in my android/settings.gradle, android/app/build.gradle, and MainActivity.java. I've recompiled, restarted the packager and all that. Hmm...

oblador commented 8 years ago

Does the IconExplorer example work for you?

apastel commented 8 years ago

Yes. And I can see the back arrow icon rendering if I click on one of the icon sets.

IconExplorer

oblador commented 8 years ago

That one is using the ToolbarAndroid integration so then it's something in your project :-) Compare them and see if you can spot any differences.

apastel commented 8 years ago

Working on it. Thanks for the help. I'll let you know what I find...

apastel commented 8 years ago

Finally got it to work. I ran react-native upgrade a second time and saw that there were still some available changes I hadn't yet merged into my android files that I must have rejected the first time around, specifically in android/build.gradle and android/app/build.gradle. I'll show the diffs here just for reference.

In android/app/build.gradle

             compile project(':react-native-facebook-login')
             compile fileTree(dir: "libs", include: ["*.jar"])
             compile "com.android.support:appcompat-v7:23.0.1"
-            compile "com.facebook.react:react-native:0.20.+"
+            compile "com.facebook.react:react-native:+"
}

And in android/build.gradle

    repositories {
         mavenLocal()
         jcenter()
+        maven {
+            // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
+            url "$projectDir/../../node_modules/react-native/android"
+        }
dorthwein commented 8 years ago

Incase anyone else comes across this - I can confirm @apastel solution and wanted to clarify you need to be sure to use react-native 0.21+

aamir-munir commented 8 years ago

Hi, I am using MaterialIcons it works fine in iPhone app but not showing icons in android. Any guess why? I follow everything explained and looks like my code have no issue, because I can see fontawesome icons fine.

Thank you

jerez commented 8 years ago

Same as @itcurves here, any clue?

WeIio commented 7 years ago

Before get image source we must wait for getImageSource finished. getImageSource is an async func, so I forward to next view in then function when getImageSource finished and certainly I got it .

WeIio commented 7 years ago

Hope help anyones

cbt2016 commented 7 years ago

Working with react-native-router-flux ,i need to put right image .the prop requires an image and using getImageSource which returns a promise ,update the state and all that makes it so heavy and not worthy .the problem is the doc is not clear at all and there is not api doc ,it is confusing ...